package wangwenjun.phase2.concurrencypattern.threadmonitor;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import util.ThreadUtil;

import java.util.concurrent.TimeUnit;

/**
 * @author ChangLiang
 * @date 2020/6/12
 */
@Slf4j
public class AppTest {

    private ReturnRunnableStateListener<String> myRunnableStateListener;

    @BeforeEach
    public void setup() {
        /**
         * through myRunnableStateListener, do callback, in callback method, can do interested things
         * 比如获取最终的计算结果等
         * 这里使用了匿名内部类 class AppTest$1
         */
        myRunnableStateListener = new ReturnRunnableStateListener.EmptyReturnRunnableStateListener<String>() {

            @Override
            public void onStart(Thread thread) {
                log.info("ExecutionThread:{}, RunnableThread:{}, Runnable start ", Thread.currentThread(), thread.getName());
            }

            @Override
            public void onRunning(Thread thread) {
                log.info("ExecutionThread:{}, RunnableThread:{}, Runnable is running ", Thread.currentThread(), thread.getName());
            }

            @Override
            public void onError(Thread thread, Exception e) {
                log.error("ExecutionThread:{}, RunnableThread:{}, Runnable is on error ", Thread.currentThread(), thread.getName());
                log.error(ThreadUtil.exceptionToString(e));
            }

            @Override
            public void onFinish(Thread thread, String result) {
                log.info("ExecutionThread:{}, RunnableThread:{}, The result is {}", Thread.currentThread(), thread.getName(), result);
            }
        };
    }

    @Test
    @DisplayName("test notifier normal")
    public void test() throws InterruptedException {

        System.out.println(myRunnableStateListener.getClass());

        // 在test方法中 通过传入RunnableStateExecutor，来对这个Task的监控
        // ReturnRunnableNotifierTask 本身的run方法充当了事件源的发起者，而myRunnableStateListener则扮演了事件回调的响应者
        // note: 其run方法以及callback method是在同一个线程中执行的
        ReturnRunnableNotifier runnableListenableTask = new ReturnRunnableNotifierTask<>(myRunnableStateListener, () -> {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.error("{} run method finished", Thread.currentThread());
            return "my runnable finished";
        }, "my-listenable-runnable-thread");

        runnableListenableTask.start();
        ((ReturnRunnableNotifierTask) runnableListenableTask).join();
    }


    @Test
    @DisplayName("test notifier error")
    public void test2() throws InterruptedException {

        ReturnRunnableNotifier runnableListenableTask = new ReturnRunnableNotifierTask<>(myRunnableStateListener, () -> {
            try {
                TimeUnit.SECONDS.sleep(10);
                int i = 1/0;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.warn("{} run method finished", Thread.currentThread());
            return "my runnable finished";
        }, "my-listenable-runnable-thread");

        runnableListenableTask.start();
        ((ReturnRunnableNotifierTask) runnableListenableTask).join();
    }

    @Test
    @DisplayName("test listener error")
    public void test3() throws InterruptedException {

        myRunnableStateListener = new ReturnRunnableStateListener.EmptyReturnRunnableStateListener<String>() {

            @Override
            public void onStart(Thread thread) {
                log.info("ExecutionThread:{}, RunnableThread:{}, Runnable start ", Thread.currentThread(), thread.getName());
            }

            @Override
            public void onRunning(Thread thread) {
                int i = 1/0;
                log.info("ExecutionThread:{}, RunnableThread:{}, Runnable is running ", Thread.currentThread(), thread.getName());
            }

            @Override
            public void onError(Thread thread, Exception e) {
                log.error("ExecutionThread:{}, RunnableThread:{}, Runnable is on error ", Thread.currentThread(), thread.getName());
                log.error(ThreadUtil.exceptionToString(e));
            }

            @Override
            public void onFinish(Thread thread, String result) {
                log.info("ExecutionThread:{}, RunnableThread:{}, The result is {}", Thread.currentThread(), thread.getName(), result);
            }
        };

        /**
         * note: 其run方法以及callback method是在同一个线程中执行的
         * listener error do not affect notifier task done
         */
        ReturnRunnableNotifier runnableListenableTask = new ReturnRunnableNotifierTask<>(myRunnableStateListener, () -> {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.warn("{} run method finished", Thread.currentThread());
            return "my runnable finished";
        }, "my-listenable-runnable-thread");

        runnableListenableTask.start();
        ((ReturnRunnableNotifierTask) runnableListenableTask).join();
    }
}
